home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XS.ZIP / UUCICO / DCP.C < prev    next >
C/C++ Source or Header  |  1992-12-18  |  23KB  |  669 lines

  1. /*--------------------------------------------------------------------*/
  2. /* d c p . c                                                          */
  3. /*                                                                    */
  4. /* Main routines for UUCICO                                           */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1989 by Andrew H. Derbyshire.             */
  9. /*                                                                    */
  10. /*    Changes Copyright (c) 1990-1992 by Kendra Electronic            */
  11. /*    Wonderworks.                                                    */
  12. /*                                                                    */
  13. /*    All rights reserved except those explicitly granted by the      */
  14. /*    UUPC/extended license agreement.                                */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*--------------------------------------------------------------------*/
  18. /*    Copyright (c) Richard H. Lamb 1985, 1986, 1987                  */
  19. /*    Changes Copyright (c) Stuart Lynne 1987                         */
  20. /*--------------------------------------------------------------------*/
  21.  
  22. /*--------------------------------------------------------------------*/
  23. /* Maintenance Notes:                                                 */
  24. /*                                                                    */
  25. /* 25Aug87 - Added a version number - Jal                             */
  26. /* 25Aug87 - Return 0 if contact made with host, or 5 otherwise.      */
  27. /* 04Sep87 - Bug causing premature sysend() fixed. - Randall Jessup   */
  28. /* 13May89 - Add date to version message  - Drew Derbyshire           */
  29. /* 17May89 - Add '-u' (until) option for login processing             */
  30. /* 01 Oct 89      Add missing function prototypes                     */
  31. /* 28 Nov 89      Add parse of incoming user id for From record       */
  32. /* 18 Mar 90      Change checktime() calls to Microsoft C 5.1         */
  33. /*--------------------------------------------------------------------*/
  34.  
  35. /*
  36.  *    $Id: DCP.C 1.7 1992/12/18 12:05:57 ahd Exp $
  37.  *
  38.  *    $Log: DCP.C $
  39.  * Revision 1.7  1992/12/18  12:05:57  ahd
  40.  * Suppress duplicate machine state messages to improve OS/2 scrolling
  41.  *
  42.  * Revision 1.6  1992/12/01  04:37:03  ahd
  43.  * Add standard comment block for header
  44.  *
  45.  * Revision 1.5  1992/11/28  19:51:16  ahd
  46.  * If in multitask mode, only open syslog on demand basis
  47.  *
  48.  * Revision 1.4  1992/11/22  21:30:55  ahd
  49.  * Do not bother to strdup() string arguments
  50.  *
  51.  */
  52.  
  53. /*--------------------------------------------------------------------*/
  54. /* This program implements a uucico type file transfer and remote     */
  55. /* execution protocol.                                                */
  56. /*                                                                    */
  57. /* Usage:   UUCICO [-s sys]                                           */
  58. /*                 [-r 0|1]                                           */
  59. /*                 [-x debug]                                         */
  60. /*                 [-d hhmm]                                          */
  61. /*                 [-m modem]                                         */
  62. /*                 [-l logfile]                                       */
  63. /*                 [-x debuglevel]                                    */
  64. /*                 [-w userid]                                        */
  65. /*                 [-z bps]                                           */
  66. /*                                                                    */
  67. /* e.g.                                                               */
  68. /*                                                                    */
  69. /* UUCICO [-x n] -r 0 [-d hhmm]    client mode, wait for an incoming  */
  70. /*                                 call for 'hhmm'.                   */
  71. /* UUCICO [-x n] -s HOST     call the host "HOST".                    */
  72. /* UUCICO [-x n] -s all      call all known hosts in the systems      */
  73. /*                           file.                                    */
  74. /* UUCICO [-x n] -s any      call any host we have work queued for.   */
  75. /* UUCICO [-x n]             same as the above.                       */
  76. /*--------------------------------------------------------------------*/
  77.  
  78. #include <stdio.h>
  79. #include <stdlib.h>
  80. #include <string.h>
  81. #include <sys/types.h>
  82. #include <limits.h>
  83. #include <time.h>
  84.  
  85. /*--------------------------------------------------------------------*/
  86. /*                      UUPC/extended prototypes                      */
  87. /*--------------------------------------------------------------------*/
  88.  
  89. #include "lib.h"
  90. #include "arpadate.h"
  91. #include "catcher.h"
  92. #include "checktim.h"
  93. #include "dcp.h"
  94. #include "dcplib.h"
  95. #include "dcpstats.h"
  96. #include "dcpsys.h"
  97. #include "dcpxfer.h"
  98. #include "expath.h"
  99. #include "getopt.h"
  100. #include "hlib.h"
  101. #include "hostable.h"
  102. #include "hostatus.h"
  103. #include "lock.h"
  104. #include "logger.h"
  105. #include "modem.h"
  106. #include "security.h"
  107. #include "ssleep.h"
  108.  
  109. /*--------------------------------------------------------------------*/
  110. /*    Define passive and active polling modes; passive is             */
  111. /*    sometimes refered to as "slave", "active" as master.  Since     */
  112. /*    the roles can actually switch during processing, we avoid       */
  113. /*    the terms here                                                  */
  114. /*--------------------------------------------------------------------*/
  115.  
  116. typedef enum {
  117.       POLL_PASSIVE = 0,       /* We answer the telephone          */
  118.       POLL_ACTIVE  = 1        /* We call out to another host      */
  119.       } POLL_MODE ;
  120.  
  121. /*--------------------------------------------------------------------*/
  122. /*                          Global variables                          */
  123. /*--------------------------------------------------------------------*/
  124.  
  125. size_t pktsize;                  /* packet size for this protocol*/
  126.  
  127. FILE *xfer_stream = NULL;        /* stream for file being handled    */
  128. boolean callnow = FALSE;           /* TRUE = ignore time in L.SYS        */
  129. FILE *fwork = NULL, *fsys= NULL ;
  130. FILE *syslog = NULL;
  131. char workfile[FILENAME_MAX];  /* name of current workfile         */
  132. char *Rmtname = nil(char);    /* system we want to call           */
  133. char rmtname[20];             /* system we end up talking to      */
  134. char s_systems[FILENAME_MAX]; /* full-name of systems file        */
  135. struct HostTable *hostp;
  136. struct HostStats remote_stats; /* host status, as defined by hostatus */
  137.  
  138. static boolean dialed = FALSE;/* True = We attempted a phone call */
  139.  
  140. currentfile();
  141.  
  142. /*--------------------------------------------------------------------*/
  143. /*                     Local function prototypes                      */
  144. /*--------------------------------------------------------------------*/
  145.  
  146. static CONN_STATE process( const POLL_MODE poll_mode, const char callgrade );
  147.  
  148. /*--------------------------------------------------------------------*/
  149. /*    d c p m a i n                                                   */
  150. /*                                                                    */
  151. /*    main program for DCP, called by uuhost                          */
  152. /*--------------------------------------------------------------------*/
  153.  
  154. int dcpmain(int argc, char *argv[])
  155. {
  156.  
  157.    char *logfile_name = NULL;
  158.    boolean  Contacted = FALSE;
  159.  
  160.    int option;
  161.    int poll_mode = POLL_ACTIVE;   /* Default = dial out to system     */
  162.    time_t exit_time = LONG_MAX;
  163.  
  164.    char recvgrade = ALL_GRADES;
  165.    boolean override_grade = FALSE;
  166.    char sendgrade = ALL_GRADES;
  167.  
  168.    char *hotuser = NULL;
  169.    BPS  hotbaud = 0;
  170.  
  171.    fwork = nil(FILE);
  172.  
  173. /*--------------------------------------------------------------------*/
  174. /*                        Process our options                         */
  175. /*--------------------------------------------------------------------*/
  176.  
  177.    while ((option = getopt(argc, argv, "d:g:m:l:r:s:w:x:z:n?")) != EOF)
  178.       switch (option)
  179.       {
  180.  
  181.       case 'd':
  182.          exit_time = atoi( optarg );
  183.          exit_time = time(NULL) + hhmm2sec(exit_time);
  184.          break;
  185.  
  186.       case 'g':
  187.          if (strlen(optarg) == 1 )
  188.             recvgrade = *optarg;
  189.          else {
  190.             recvgrade = checktime( optarg );
  191.                                  /* Get restriction for this hour */
  192.             if ( ! recvgrade )   /* If no class, use the default  */
  193.                recvgrade = ALL_GRADES;
  194.          }
  195.          override_grade = TRUE;
  196.          break;
  197.  
  198.       case 'm':                     /* Override in modem name     */
  199.          E_inmodem = optarg;
  200.          poll_mode = 0;             /* Presume passive polling */
  201.          break;
  202.  
  203.       case 'l':                     /* Log file name              */
  204.          logfile_name = optarg;
  205.          break;
  206.  
  207.       case 'n':
  208.          callnow = TRUE;
  209.          break;
  210.  
  211.       case 'r':
  212.          poll_mode = atoi(optarg);
  213.          break;
  214.  
  215.       case 's':
  216.          Rmtname = optarg;
  217.          break;
  218.  
  219.       case 'x':
  220.          debuglevel = atoi(optarg);
  221.          break;
  222.  
  223.       case 'z':
  224.          hotbaud = atoi(optarg);
  225.          break;
  226.  
  227.       case 'w':
  228.          poll_mode = 0;       /* Presume passive polling */
  229.          hotuser = optarg;
  230.          break;
  231.  
  232.       case '?':
  233.          puts("\nUsage:\tuucico\t"
  234.          "[-s [all | any | sys]] [-r 1|0] [-x debug] [-d hhmm]\n"
  235.          "\t\t[-n] [-w user] [-l logfile] [-m modem] [-z bps]");
  236.          return 4;
  237.       }
  238.  
  239. /*--------------------------------------------------------------------*/
  240. /*                Abort if any options were left over                 */
  241. /*--------------------------------------------------------------------*/
  242.  
  243.    if (optind != argc) {
  244.       puts("Extra parameter(s) at end.");
  245.       return 4;
  246.    }
  247.  
  248.    if (Rmtname == nil(char))
  249.       Rmtname = "any";
  250.  
  251. /*--------------------------------------------------------------------*/
  252. /*        Initialize logging and the name of the systems file         */
  253. /*--------------------------------------------------------------------*/
  254.  
  255.    openlog( logfile_name );
  256.  
  257.    if (bflag[F_SYSLOG] && ! bflag[F_MULTITASK] &&
  258.       (syslog = FOPEN(SYSLOG, "a", TEXT)) == nil(FILE))
  259.    {
  260.       printerr( SYSLOG );
  261.       panic();
  262.    }
  263.  
  264.    mkfilename(s_systems, E_confdir, SYSTEMS);
  265.    printmsg(2, "Using system file '%s'",s_systems);
  266.  
  267.    if ( terminate_processing )
  268.       return 100;
  269.  
  270. /*--------------------------------------------------------------------*/
  271. /*                        Initialize security                         */
  272. /*--------------------------------------------------------------------*/
  273.  
  274.    if ( !LoadSecurity())
  275.    {
  276.       printmsg(0,"Unable to initialize security, see previous message");
  277.       panic();
  278.    }
  279.  
  280.    if ( terminate_processing )
  281.       return 100;
  282.  
  283.    atexit( shutdown );        /* Insure port is closed by panic()    */
  284.    remote_stats.save_hstatus = nocall;
  285.                               /* Known state for automatic status
  286.                                  update                              */
  287.  
  288. /*--------------------------------------------------------------------*/
  289. /*                     Begin main processing loop                     */
  290. /*--------------------------------------------------------------------*/
  291.  
  292.    if (poll_mode == POLL_ACTIVE) {
  293.  
  294.       CONN_STATE m_state = CONN_INITSTAT;
  295.       CONN_STATE old_state = CONN_EXIT;
  296.  
  297.       printmsg(2, "calling \"%s\", debug=%d", Rmtname, debuglevel);
  298.  
  299.       if ((fsys = FOPEN(s_systems, "r", TEXT)) == nil(FILE))
  300.          exit(FAILED);
  301.  
  302.       setvbuf( fsys, NULL, _IONBF, 0);
  303.  
  304.       while (m_state != CONN_EXIT )
  305.       {
  306.          printmsg(old_state == m_state ? 10 : 4 ,
  307.                   "M state = %c", m_state);
  308.          old_state = m_state;
  309.  
  310.          if (bflag[F_MULTITASK] &&
  311.               (hostp != NULL ) &&
  312.               (remote_stats.save_hstatus != hostp->hstatus ))
  313.          {
  314.             dcupdate();
  315.             remote_stats.save_hstatus = hostp->hstatus;
  316.          }
  317.  
  318.          switch (m_state)
  319.          {
  320.             case CONN_INITSTAT:
  321.                HostStatus();
  322.                m_state = CONN_INITIALIZE;
  323.                break;
  324.  
  325.             case CONN_INITIALIZE:
  326.                hostp = NULL;
  327.  
  328.                if ( locked )
  329.                   UnlockSystem();
  330.  
  331.                m_state = getsystem(recvgrade);
  332.                if ( hostp != NULL )
  333.                   remote_stats.save_hstatus = hostp->hstatus;
  334.                break;
  335.  
  336.             case CONN_CALLUP1:
  337.                sendgrade = checktime(flds[FLD_CCTIME]);
  338.  
  339.                if ( (override_grade && sendgrade) || callnow )
  340.                   sendgrade = recvgrade;
  341.  
  342.                if ( !CallWindow( sendgrade ))
  343.                   m_state = CONN_INITIALIZE;
  344.                else if ( LockSystem( hostp->hostname , B_UUCICO))
  345.                {
  346.                   dialed = TRUE;
  347.                   time(&hostp->hstats->ltime);
  348.                                  /* Save time of last attempt to call   */
  349.                   hostp->hstatus = autodial;
  350.                   m_state = CONN_CALLUP2;
  351.                }
  352.                else
  353.                   m_state = CONN_INITIALIZE;
  354.  
  355.                break;
  356.  
  357.             case CONN_CALLUP2:
  358.                m_state = callup( );
  359.  
  360.                break;
  361.  
  362.             case CONN_PROTOCOL:
  363.                m_state = startup_server( (char)
  364.                                           (bflag[F_SYMMETRICGRADES] ?
  365.                                           sendgrade  : recvgrade) );
  366.                break;
  367.  
  368.             case CONN_SERVER:
  369.                m_state = process( poll_mode, recvgrade );
  370.                Contacted = TRUE;
  371.                break;
  372.  
  373.             case CONN_TERMINATE:
  374.                m_state = sysend();
  375.                if ( hostp != NULL )
  376.                   dcstats();
  377.                break;
  378.  
  379.             case CONN_DROPLINE:
  380.                shutdown();
  381.                UnlockSystem();
  382.                m_state = CONN_INITIALIZE;
  383.                break;
  384.  
  385.             case CONN_EXIT:
  386.                break;
  387.  
  388.             default:
  389.                printmsg(0,"dcpmain: Unknown master state = %c",m_state );
  390.                panic();
  391.                break;
  392.          } /* switch */
  393.  
  394.          if ( terminate_processing )
  395.             m_state = CONN_EXIT;
  396.  
  397.       } /* while */
  398.       fclose(fsys);
  399.  
  400.    }
  401.    else { /* client mode */
  402.  
  403.       CONN_STATE s_state = CONN_INITIALIZE;
  404.       CONN_STATE old_state = CONN_EXIT;
  405.  
  406.       while (s_state != CONN_EXIT )
  407.       {
  408.          printmsg(s_state == old_state ? 10 : 4 ,
  409.                   "S state = %c", s_state);
  410.          old_state = s_state;
  411.  
  412.          if (bflag[F_MULTITASK] &&
  413.               (hostp != NULL ) &&
  414.               (remote_stats.save_hstatus != hostp->hstatus ))
  415.          {
  416.             printmsg(2, "Updating status for host %s, status %d",
  417.                         hostp->hostname ,
  418.                         (int) hostp->hstatus );
  419.             dcupdate();
  420.             remote_stats.save_hstatus = hostp->hstatus;
  421.          }
  422.  
  423.          switch (s_state) {
  424.             case CONN_INITIALIZE:
  425.                if ( hotuser == NULL )
  426.                   s_state = CONN_ANSWER;
  427.                else
  428.                   s_state = CONN_HOTMODEM;
  429.                break;
  430.  
  431.             case CONN_ANSWER:
  432.                s_state = callin( exit_time );
  433.                break;
  434.  
  435.             case CONN_HOTMODEM:
  436.                s_state = callhot( hotbaud );
  437.                break;
  438.  
  439.             case CONN_HOTLOGIN:
  440.                if ( loginbypass( hotuser ) )
  441.                   s_state = CONN_INITSTAT;
  442.                else
  443.                   s_state = CONN_DROPLINE;
  444.                break;
  445.  
  446.             case CONN_LOGIN:
  447.                if ( login( ) )
  448.                   s_state = CONN_INITSTAT;
  449.                else
  450.                   s_state = CONN_DROPLINE;
  451.                break;
  452.  
  453.             case CONN_INITSTAT:
  454.                HostStatus();
  455.                s_state = CONN_PROTOCOL;
  456.                break;
  457.  
  458.             case CONN_PROTOCOL:
  459.                s_state = startup_client(&sendgrade);
  460.                break;
  461.  
  462.             case CONN_CLIENT:
  463.                Contacted = TRUE;
  464.                s_state = process( poll_mode, sendgrade );
  465.                break;
  466.  
  467.             case CONN_TERMINATE:
  468.                s_state = sysend();
  469.                if ( hostp != NULL )
  470.                   dcstats();
  471.                break;
  472.  
  473.             case CONN_DROPLINE:
  474.                shutdown();
  475.                if ( locked )     /* Cause could get here w/o
  476.                                     locking                    */
  477.                   UnlockSystem();
  478.                s_state = CONN_EXIT;
  479.  
  480.             case CONN_EXIT:
  481.                break;
  482.  
  483.             default:
  484.                printmsg(0,"dcpmain: Unknown slave state = %c",s_state );
  485.                panic();
  486.                break;
  487.          } /* switch */
  488.  
  489.          if ( terminate_processing )
  490.             s_state = CONN_EXIT;
  491.  
  492.       } /* while */
  493.    } /* else */
  494.  
  495. /*--------------------------------------------------------------------*/
  496. /*                         Report our results                         */
  497. /*--------------------------------------------------------------------*/
  498.  
  499.    if (!Contacted && (poll_mode == POLL_ACTIVE))
  500.    {
  501.       if (dialed)
  502.          printmsg(0, "Could not connect to remote system.");
  503.       else
  504.          printmsg(0,
  505.                "No work for requested system or wrong time to call.");
  506.    }
  507.  
  508.    dcupdate();
  509.  
  510.    if (bflag[F_SYSLOG] && ! bflag[F_MULTITASK])
  511.       fclose(syslog);
  512.  
  513.    return terminate_processing ? 100 : (Contacted ? 0 : 5);
  514.  
  515. } /*dcpmain*/
  516.  
  517.  
  518. /*--------------------------------------------------------------------*/
  519. /*    p r o c e s s                                                   */
  520. /*                                                                    */
  521. /*    The procotol state machine                                      */
  522. /*--------------------------------------------------------------------*/
  523.  
  524. static CONN_STATE process( const POLL_MODE poll_mode, const char callgrade )
  525. {
  526.    boolean master  = ( poll_mode == POLL_ACTIVE );
  527.    boolean aborted = FALSE;
  528.    XFER_STATE state =  master ? XFER_SENDINIT : XFER_RECVINIT;
  529.    XFER_STATE old_state = XFER_EXIT;
  530.                               /* Initialized to any state but the
  531.                                  original value of "state"           */
  532.    XFER_STATE save_state = XFER_EXIT;
  533.  
  534. /*--------------------------------------------------------------------*/
  535. /*  Yea old state machine for the high level file transfer procotol   */
  536. /*--------------------------------------------------------------------*/
  537.  
  538.    while( state != XFER_EXIT )
  539.    {
  540.       printmsg(state == old_state ? 14 : 4 ,
  541.                "process: Machine state is = %c", state );
  542.       old_state = state;
  543.  
  544.       if ( terminate_processing != aborted )
  545.       {
  546.          aborted = terminate_processing;
  547.          state = XFER_ABORT;
  548.       }
  549.  
  550.       switch( state )
  551.       {
  552.  
  553.          case XFER_SENDINIT:  /* Initialize outgoing protocol        */
  554.             state = sinit();
  555.             break;
  556.  
  557.          case XFER_RECVINIT:  /* Initialize Receive protocol         */
  558.             state = rinit();
  559.             break;
  560.  
  561.          case XFER_MASTER:    /* Begin master mode                   */
  562.             master = TRUE;
  563.             state = XFER_NEXTJOB;
  564.             break;
  565.  
  566.          case XFER_SLAVE:     /* Begin slave mode                    */
  567.             master = FALSE;
  568.             state = XFER_RECVHDR;
  569.             break;
  570.  
  571.          case XFER_NEXTJOB:   /* Look for work in local queue        */
  572.             state = scandir( rmtname, callgrade );
  573.             break;
  574.  
  575.          case XFER_REQUEST:   /* Process next file in current job
  576.                                  in queue                            */
  577.             state = newrequest();
  578.             break;
  579.  
  580.          case XFER_PUTFILE:   /* Got local tranmit request           */
  581.             state = ssfile();
  582.             break;
  583.  
  584.          case XFER_GETFILE:   /* Got local tranmit request           */
  585.             state = srfile();
  586.             break;
  587.  
  588.          case XFER_SENDDATA:  /* Remote accepted our work, send data */
  589.             state = sdata();
  590.             break;
  591.  
  592.          case XFER_SENDEOF:   /* File xfer complete, send EOF        */
  593.             state = seof( master );
  594.             break;
  595.  
  596.          case XFER_FILEDONE:  /* Receive or transmit is complete     */
  597.             state = master ? XFER_REQUEST : XFER_RECVHDR;
  598.             break;
  599.  
  600.          case XFER_NOLOCAL:   /* No local work, remote have any?     */
  601.             state = sbreak();
  602.             break;
  603.  
  604.          case XFER_NOREMOTE:  /* No remote work, local have any?     */
  605.             state = schkdir( poll_mode == POLL_ACTIVE, callgrade );
  606.             break;
  607.  
  608.          case XFER_RECVHDR:   /* Receive header from other host      */
  609.             state = rheader();
  610.             break;
  611.  
  612.          case XFER_TAKEFILE:  /* Set up to receive remote requested
  613.                                  file transfer                       */
  614.             state = rrfile();
  615.             break;
  616.  
  617.          case XFER_GIVEFILE:  /* Set up to transmit remote
  618.                                  requuest file transfer              */
  619.             state = rsfile();
  620.             break;
  621.  
  622.          case XFER_RECVDATA:  /* Receive file data from other host   */
  623.             state = rdata();
  624.             break;
  625.  
  626.          case XFER_RECVEOF:
  627.             state = reof();
  628.             break;
  629.  
  630.          case XFER_LOST:      /* Lost the other host, flame out      */
  631.             printmsg(0,"process: Connection lost to %s, "
  632.                        "previous system state = %c",
  633.                        rmtname, save_state );
  634.             hostp->hstatus = call_failed;
  635.             state = XFER_EXIT;
  636.             break;
  637.  
  638.          case XFER_ABORT:     /* Internal error, flame out           */
  639.             printmsg(0,"process: Aborting connection to %s, "
  640.                        "previous system state = %c",
  641.                        rmtname, save_state );
  642.             hostp->hstatus = call_failed;
  643.             state = XFER_ENDP;
  644.             break;
  645.  
  646.          case XFER_ENDP:      /* Terminate the protocol              */
  647.             state = endp();
  648.             break;
  649.  
  650.          default:
  651.             printmsg(0,"process: Unknown state = %c, "
  652.                        "previous system state = %c",
  653.                        state, save_state );
  654.             state = XFER_ABORT;
  655.             break;
  656.       } /* switch */
  657.  
  658.       save_state = old_state; /* Used only if we abort               */
  659.  
  660.    } /* while( state != XFER_EXIT ) */
  661.  
  662. /*--------------------------------------------------------------------*/
  663. /*           Protocol is complete, terminate the connection           */
  664. /*--------------------------------------------------------------------*/
  665.  
  666.    return CONN_TERMINATE;
  667.  
  668. } /* process */
  669.